package cn.catsdad.service.impl;

import cn.catsdad.base.page.PageBean;
import cn.catsdad.base.page.PageParam;
import cn.catsdad.base.service.impl.BaseCrudServiceImpl;
import cn.catsdad.dto.DictDTO;
import cn.catsdad.dto.DictDetailDTO;
import cn.catsdad.exception.BaseException;
import cn.catsdad.repository.DictRepository;
import cn.catsdad.service.api.DictDetailService;
import cn.catsdad.service.api.DictService;
import cn.catsdad.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 常量管理service实现
 *
 * @author xuyonglong
 * @version V1.0 2023/4/24
 */
@Service
public class DictServiceImpl extends BaseCrudServiceImpl<DictDTO, Long, DictRepository> implements DictService {

    private DictDetailService detailService;

    @Override
    public void pageQuery(PageBean<DictDTO> page, PageParam param) {
        page.setEntityName("DtoDict d").setQuery("select d");
        super.pageQuery(page, param);
    }

    @Override
    @Transactional
    public DictDTO save(DictDTO entity) {
        validation(entity);
        return super.save(entity);
    }

    @Override
    public DictDTO queryById(Long aLong) {
        Map<Long, List<DictDetailDTO>> details = detailService.queryDetailByDictIds(Collections.singleton(aLong));
        DictDTO result = super.queryById(aLong);
        result.setDetailList(details.get(aLong));
        return result;
    }

    @Override
    @Transactional
    public void logicDeleteByIds(Collection<Long> ids) {
        detailService.deleteByDictIds(ids);
        super.logicDeleteByIds(ids);
    }

    @Override
    @Transactional
    public DictDTO update(DictDTO entity) {
        validation(entity);
        return super.update(entity);
    }

    @Override
    public List<DictDetailDTO> queryChildrenByDictCode(String dictCode) {
        List<DictDetailDTO> result = new ArrayList<>();
        if (StringUtil.isNotEmpty(dictCode)) {
            DictDTO dictDTO = repository.findFirstByCodeAndIsDeletedFalse(dictCode);
            if (dictDTO != null) {
                result = detailService.queryByDictIdAndIsDeletedFalse(dictDTO.getId());
            }
        }
        return result;
    }

    @Override
    public Map<String, Map<String, DictDetailDTO>> queryChildrenByDictCodes(String... dictCodes) {
        Map<String, Map<String, DictDetailDTO>> result = new HashMap<>(dictCodes.length);
        if (dictCodes.length > 0) {
            List<DictDTO> dicts = repository.findByCodeIn(Arrays.asList(dictCodes));
            List<Long> dictIds = dicts.stream().map(DictDTO::getId).collect(Collectors.toList());
            List<DictDetailDTO> details = detailService.queryByDictIds(dictIds);
            if (StringUtil.isNotEmpty(details)) {
                Map<Long, List<DictDetailDTO>> detailMap = details.stream().collect(Collectors.groupingBy(DictDetailDTO::getDictId));
                for (DictDTO dict : dicts) {
                    List<DictDetailDTO> detailsOfDict = detailMap.get(dict.getId()) == null ? new ArrayList<>() : detailMap.get(dict.getId());
                    Map<String, DictDetailDTO> dictDetailMap = new HashMap<>(detailsOfDict.size());
                    for (DictDetailDTO dictDetail : detailsOfDict) {
                        dictDetailMap.put(dictDetail.getCode(), dictDetail);
                    }
                    result.put(dict.getCode(), dictDetailMap);
                }
            }
        }
        return result;
    }

    @Override
    public Map<String, DictDetailDTO> queryChildrenDictMap(String dictCode) {
        List<DictDetailDTO> details = queryChildrenByDictCode(dictCode);
        Map<String, DictDetailDTO> result = new HashMap<>(details.size());
        for (DictDetailDTO detail : details) {
            result.put(detail.getCode(), detail);
        }
        return result;
    }

    /**
     * 唯一性验证
     *
     * @param dictDTO 需要验证的常量
     */
    private void validation(DictDTO dictDTO) {
        Integer count = repository.countByNameAndCodeAndIdNotAndIsDeletedFalse(dictDTO.getName(), dictDTO.getCode(), dictDTO.getId());
        if (count > 0) {
            throw new BaseException("已存在当前常量数据！");
        }
    }

    @Autowired
    public void setDetailService(DictDetailService detailService) {
        this.detailService = detailService;
    }
}
